function Swipper(el, opt) {

	opt = $.extend({
		navigation: {}
	}, opt);

	var swiperID = this.$swiper = $(el)

	if(swiperID.length < 1) {
		return
	}

	// 在这个元素上设置滚动的距离
	this.$swiperWrapper = swiperID.find(opt.wrapperClass || ".swipper-wrapper");

	// 获取有多少屏
	var $swiperItem = this.$swiperItem = swiperID.find(opt.itemClass || ".swipper-slide");
	var swiperheight =this.$swiperHeight = this.$swiperItem.height()

	this.activeIndex = 0 // 当前激活项
	this.$swiperCount = $swiperItem.length; // 有多少个滚动项
	this.defaultSpeed =.3; // 滚动的速度，滚动的距离 / 滚动的时间
	this.maxDistance = swiperheight / 2 // 滚动距离限值，超过这个值就自动滚动下一张
	this.animating = false // 是否正在滚动，如果正在滚动，那么就禁止滑动
	this.bindEvent()

}

Swipper.prototype = {

	bindEvent() {

		var deltaY = 0; // 不能改变的一个值，所以不能再touchmove中改变
		var time = 0
		var _this = this;
		var distance = 0; // 当前手指移动的距离
		var isMobile = Utils.isMobile()
		var drag = false; // pc 端下 禁止mousemove 触发

		var swiper = this.$swiper;

		swiper.on(isMobile ? "touchstart" : "mousedown", function(ev) {

            /**
             * 别人：开发中发现：transitionend 在某些情况下未被触发，导致 animating 一直为 true，从而拒绝用户响应
             * 因此，需要获取当前 translateY 的值，判断其是否处于 activeIndex 的初始位置，若是则代表过渡完毕
             * 
             * 我：因为动画还没完成，用户就马上拖动了，马上触发了 touchstart，而且 touchmove已经在运行，
             * 虽然不会影响此次动画的完成，
             * 但是会导致动画完成之后，
             * 立即进入了 用户第二次拖动的动作中，拖动距离马上变成 动画完成前的 移动的距离，会很突兀
             * 
             * 测试：把 defaultSpeed 调成3s 就可以看到很明显的效果了
             * */
            var translate = Utils.getTranslate(_this.$swiperWrapper[0], 'y')
            
			if(translate === -_this.activeIndex * _this.$swiperHeight) {

				drag = swiper
				deltaY = _this.getTouchY(ev)
				time = new Date()
				_this.animating = false

			} else {
				drag = false
			}

//			deltaY = _this.getTouchY(ev)
//			time = new Date()
//			drag=true

		})

		swiper.on(isMobile ? "touchmove" : "mousemove", function(ev) {

			if(drag) {
				distance = _this.getTouchY(ev) - deltaY
				_this.panTranslate(distance)
			}

		})

		swiper.on(isMobile ? "touchend" : "mouseup", function(ev) {

			var interval = new Date() - time;

			_this.panEnd(distance / interval, distance);

			drag = false

		})

		this.$swiperWrapper.on("transitionend", this.transitionEndHandle.bind(this))

	},

	// 元素随手指移动距离而移动
	panTranslate(offset) {

//		console.log("animating--->",this.animating)
		if(this.animating) {
			return
		}

		// 当前活跃块的位移 + 拖拽距离
		offset = -this.activeIndex * this.$swiperHeight + offset

		this.$swiperWrapper.css({
			"transform": "translate3d(0," + offset + "px,0)",
			"transition": "none"
		})

	},

	// 手指移动结束，元素需要如何调整，是归位，还是移至其他
	panEnd(speed, deltaY) {

		if(this.animating) return

		var absDis = Math.abs(deltaY);
		var absSpeed = Math.abs(speed);

		var canSide = absDis >= this.maxDistance || absSpeed >= this.defaultSpeed

		//		console.log(deltaY < 0, canSide, absDis >= this.maxDistance, absSpeed <= this.defaultSpeed)

		// 滑动距离为 正，那么就是向下滑动，那么就是上一张
		if(deltaY > 0 && this.activeIndex > 0) {

			if(canSide) {
				this.slidePrev()
			} else {

				this.slideTo()
			}

		}

		// 滑动距离为 负，那么就是向上滑动，那么就是下一张
		else if(deltaY < 0 && this.activeIndex < this.$swiperCount - 1) {

			if(canSide) {

				this.slideNext()
			} else {

				this.slideTo()
			}

		} else {
			this.slideTo()
		}

	},

	// 因为pc 和移动端的点击y坐标获取不一样
	getTouchY(ev) {
		return Utils.isMobile() ? ev.touches[0].pageY : ev.pageY
	},
	
	// 动画完成，把标志位重置，但是很有可能这个动画并不是移动的动画，所以要判断一下
    transitionEndHandle(ev) {
    	
        if (['transform', 'webkitTransform'].indexOf(ev.propertyName) !== -1) {
            this.animating = false
        }

    },
	
	// 整屏滚动
	slideTo(index, speed) {

		var offset = -(typeof index !== "undefined" ? index : this.activeIndex) * this.$swiperHeight;
		var _speed = typeof speed == "undefined" ? this.defaultSpeed : speed;
		this.activeIndex = typeof index !== "undefined" ? index : this.activeIndex;
		
//		console.log("slideTo")
		if(_speed > 0) {
			this.animating = true
		}

		this.$swiperWrapper.css({
			"transform": "translate3d(0," + offset + "px,0)",
			"transition": "transform " + _speed + "s"
		})
	},
	
	// 滚动到下一张
	slideNext() {

		var currentIndex = this.activeIndex + 1

		if(currentIndex >= this.$swiperCount) {
			return
		}

		this.slideTo(currentIndex)
	},
	
	// 滚动回上一张
	slidePrev() {

		var currentIndex = this.activeIndex - 1

		if(currentIndex < 0) {
			return
		}

		this.slideTo(currentIndex)
	}

}